package me.sealer.utils;

/**
 * 功能描述： $ NumberUtil
 *
 * @author sealer
 * @email 1178884049@qq.com
 * @date 2019年08月27日 15时48分02秒
 */
public class NumberUtil {
    /**
     * 此方法为JDK1.8中的Integer.reverse(int i)的源码， 此处金座分析其实现思想。
     *
     * @param i 待按位翻转的整数
     * @return 翻转后的整数
     */
    public static int reverseIntByBit(int i) {
        // 将32位的整数相邻两位翻转， 如： i1i0 i3i2 i5i4 ... i31i30
        // 0x55555555 即： 0101 0101 0101 0101  0101 0101 0101 0101
        i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

        // 将32位的整数相邻四位以两位为一个整体翻转， 如： i3i2i1i0  i7i6i5i4 ... i31i30i29i28
        // 0x33333333 即： 0011 0011 0011 0011 0011 0011 0011 0011
        i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

        // 将32位的整数相邻八位以四位为一个整体翻转， 如： i7i6i5i4i3i2i1i0   ... i31i30i29i28i27i26i25i24
        // 0x0f0f0f0f 即： 0000 1111 0000 1111 0000 1111 0000 1111
        i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

        // 其实目前的顺序只变成了四大块： i7~i0、i15~i8、i23~i16、i31~i24，只要将这四块做byte翻转就解决问题了。所以这块代码 是Integer.reverseByte的另一种写法， 原理一样。
        // 0xff00 即： 0000  0000  0000  0000 1111 1111 0000 0000
        i = (i << 24) | ((i & 0xff00) << 8) |
                ((i >>> 8) & 0xff00) | (i >>> 24);
        return i;
    }

    /**
     * 此代码为Integer.reverseByte的源码，现原理解析
     * 我们知道整数由4 byte组成，从高到低我们定义为： 高一位，高二位，低二位， 低一位。
     *
     * @param i 待按byte翻转的整数
     * @return 翻转后的整数
     */
    public static int reverseIntByByte(int i) {
        // i无符号右移24位， 将高一位移到了低一位，高位补零
        return ((i >>> 24)) |

                // 0xFF00 即： 00000000 00000000 11111111 00000000
                // 此行代码将高二位移到了低二位
                ((i >> 8) & 0xFF00) |

                // 0xFF0000 即： 00000000 11111111 00000000 00000000
                // 此行代码将低二位移到了高二位
                ((i << 8) & 0xFF0000) |

                // 此行代码将低一位移到来了高一位， 低位补零
                ((i << 24));
    }
}
